home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 1843 / 1843.xpi / content / firebug / chrome.js < prev    next >
Text File  |  2010-01-15  |  45KB  |  1,454 lines

  1. /* See license.txt for terms of usage */
  2.  
  3. var Firebug = null;
  4. var FirebugContext = null;
  5.  
  6. if(!fbXPCOMUtils)
  7.     throw "Failed to load FBL";
  8.  
  9. (function() { with (fbXPCOMUtils) {
  10.  
  11. // ************************************************************************************************
  12. // Constants
  13.  
  14. const Cc = Components.classes;
  15. const Ci = Components.interfaces;
  16. const nsIWebNavigation = Ci.nsIWebNavigation;
  17.  
  18. const LOAD_FLAGS_BYPASS_PROXY = nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY;
  19. const LOAD_FLAGS_BYPASS_CACHE = nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE;
  20. const LOAD_FLAGS_NONE = nsIWebNavigation.LOAD_FLAGS_NONE;
  21.  
  22. // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  23.  
  24. const panelURL = "chrome://firebug/content/panel.html";
  25.  
  26. const statusCropSize = 20;
  27.  
  28. const positiveZoomFactors = [1, 1.1, 1.2, 1.3, 1.5, 2, 3];
  29. const negativeZoomFactors = [1, 0.95, 0.8, 0.7, 0.5, 0.2, 0.1];
  30.  
  31. // ************************************************************************************************
  32. // Globals
  33.  
  34. var panelBox, panelSplitter, sidePanelDeck, panelBar1, panelBar2, locationList, locationSeparator,
  35.     panelStatus, panelStatusSeparator;
  36.  
  37. var waitingPanelBarCount = 2;
  38.  
  39. var inDetachedScope = (window.location == "chrome://firebug/content/firebug.xul");
  40.  
  41. var disabledHead = null;
  42. var disabledCaption = null;
  43. var enableSiteLink = null;
  44. var enableSystemPagesLink = null;
  45. var enableAlwaysLink = null;
  46. // ************************************************************************************************
  47.  
  48. top.FirebugChrome =
  49. {
  50.     window: window,
  51.  
  52.     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  53.     // Initialization
  54.  
  55.     panelBarReady: function(panelBar)
  56.     {
  57.         try
  58.         {
  59.             // Wait until all panelBar bindings are ready before initializing
  60.             if (--waitingPanelBarCount == 0)
  61.                 this.initialize();
  62.             else
  63.                 return false;
  64.         }
  65.         catch (exc)
  66.         {
  67.             return false;
  68.         }
  69.         return true; // the panel bar is ready
  70.     },
  71.  
  72.     initialize: function()
  73.     {
  74.         if (window.arguments)
  75.             var detachArgs = window.arguments[0];
  76.  
  77.         if (!detachArgs)
  78.             detachArgs = {};
  79.  
  80.         if (detachArgs.FBL)
  81.             top.FBL = detachArgs.FBL;
  82.         else
  83.         {
  84.             FBL.initialize();
  85.         }
  86.  
  87.         if (detachArgs.Firebug)
  88.         {
  89.             Firebug = detachArgs.Firebug;
  90.             FirebugContext = detachArgs.FirebugContext;
  91.         }
  92.         else
  93.             Firebug.initialize();
  94.  
  95.         Firebug.internationalizeUI(window.document);
  96.  
  97.         panelBox = $("fbPanelBox");
  98.         panelSplitter = $("fbPanelSplitter");
  99.         sidePanelDeck = $("fbSidePanelDeck");
  100.         panelBar1 = $("fbPanelBar1");
  101.         panelBar2 = $("fbPanelBar2");
  102.         locationList = $("fbLocationList");
  103.         locationSeparator = $("fbLocationSeparator");
  104.         panelStatus = $("fbPanelStatus");
  105.         panelStatusSeparator = $("fbStatusSeparator");
  106.  
  107.         var browser1 = panelBar1.browser;
  108.         browser1.addEventListener("load", browser1Loaded, true);
  109.  
  110.         var browser2 = panelBar2.browser;
  111.         browser2.addEventListener("load", browser2Loaded, true);
  112.  
  113.         window.addEventListener("blur", onBlur, true);
  114.  
  115.         // Initialize Firebug Tools & Firebug Icon menus.
  116.         var firebugMenuPopup = $("fbFirebugMenuPopup");
  117.         this.initializeMenu($("menu_firebug"), firebugMenuPopup);
  118.         this.initializeMenu($("fbFirebugMenu"), firebugMenuPopup);
  119.  
  120.     },
  121.  
  122.     initializeMenu: function(parentMenu, popupMenu)
  123.     {
  124.         if (!parentMenu)
  125.             return;
  126.  
  127.         if (parentMenu.getAttribute("initialized"))
  128.             return;
  129.  
  130.         parentMenu.appendChild(popupMenu.cloneNode(true));
  131.         parentMenu.setAttribute("initialized", "true");
  132.     },
  133.  
  134.     /**
  135.      * Called when the UI is ready to be initialized, once the panel browsers are loaded.
  136.      */
  137.     initializeUI: function()
  138.     {
  139.         // we listen for panel update
  140.         Firebug.registerUIListener(this);
  141.  
  142.         try {
  143.             if (window.arguments)
  144.                 var detachArgs = window.arguments[0];
  145.  
  146.             this.applyTextSize(Firebug.textSize);
  147.  
  148.             var doc1 = panelBar1.browser.contentDocument;
  149.             doc1.addEventListener("mouseover", onPanelMouseOver, false);
  150.             doc1.addEventListener("mouseout", onPanelMouseOut, false);
  151.             doc1.addEventListener("mousedown", onPanelMouseDown, false);
  152.             doc1.addEventListener("click", onPanelClick, false);
  153.             panelBar1.addEventListener("selectingPanel", onSelectingPanel, false);
  154.  
  155.             var doc2 = panelBar2.browser.contentDocument;
  156.             doc2.addEventListener("mouseover", onPanelMouseOver, false);
  157.             doc2.addEventListener("mouseout", onPanelMouseOut, false);
  158.             doc2.addEventListener("click", onPanelClick, false);
  159.             doc2.addEventListener("mousedown", onPanelMouseDown, false);
  160.             panelBar2.addEventListener("selectPanel", onSelectedSidePanel, false);
  161.  
  162.             var mainTabBox = panelBar1.ownerDocument.getElementById("fbPanelBar1-tabBox");
  163.             mainTabBox.addEventListener("mousedown", onMainTabBoxMouseDown, false);
  164.  
  165.             // The side panel bar doesn't care about this event.  It must, however,
  166.             // prevent it from bubbling now that we allow the side panel bar to be
  167.             // *inside* the main panel bar.
  168.             function stopBubble(event) { event.stopPropagation(); }
  169.             panelBar2.addEventListener("selectingPanel", stopBubble, false);
  170.  
  171.             locationList.addEventListener("selectObject", onSelectLocation, false);
  172.  
  173.             this.updatePanelBar1(Firebug.panelTypes);
  174.  
  175.             if (inDetachedScope)
  176.                 this.attachBrowser(FirebugContext);
  177.             else
  178.                 Firebug.initializeUI(detachArgs);
  179.  
  180.         } catch (exc) {
  181.             FBTrace.sysout("chrome.initializeUI fails "+exc, exc);
  182.         }
  183.     },
  184.  
  185.     shutdown: function()
  186.     {
  187.         var doc1 = panelBar1.browser.contentDocument;
  188.         doc1.removeEventListener("mouseover", onPanelMouseOver, false);
  189.         doc1.removeEventListener("mouseout", onPanelMouseOut, false);
  190.         doc1.removeEventListener("mousedown", onPanelMouseDown, false);
  191.         doc1.removeEventListener("click", onPanelClick, false);
  192.  
  193.         var doc2 = panelBar2.browser.contentDocument;
  194.         doc2.removeEventListener("mouseover", onPanelMouseOver, false);
  195.         doc2.removeEventListener("mouseout", onPanelMouseOut, false);
  196.         doc2.removeEventListener("mousedown", onPanelMouseDown, false);
  197.         doc2.removeEventListener("click", onPanelClick, false);
  198.  
  199.         var mainTabBox = panelBar1.ownerDocument.getElementById("fbPanelBar1-tabBox");
  200.         mainTabBox.removeEventListener("mousedown", onMainTabBoxMouseDown, false);
  201.  
  202.         locationList.removeEventListener("selectObject", onSelectLocation, false);
  203.  
  204.         window.removeEventListener("blur", onBlur, true);
  205.  
  206.         Firebug.unregisterUIListener(this);
  207.  
  208.         if (inDetachedScope)
  209.             this.undetach();
  210.         else
  211.             Firebug.shutdown();
  212.     },
  213.  
  214.     updateOption: function(name, value)
  215.     {
  216.         if (panelBar1.selectedPanel)
  217.             panelBar1.selectedPanel.updateOption(name, value);
  218.         if (panelBar2.selectedPanel)
  219.             panelBar2.selectedPanel.updateOption(name, value);
  220.  
  221.         if (name == "textSize")
  222.             this.applyTextSize(value);
  223.         if (name =="omitObjectPathStack")
  224.             this.obeyOmitObjectPathStack(value);
  225.     },
  226.  
  227.     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  228.  
  229.     attachBrowser: function(context)  // XXXjjb context == (FirebugContext || null)  and inDetachedScope == true
  230.     {
  231.         if (inDetachedScope)  // then we are initializing in external window
  232.         {
  233.             Firebug.setChrome(this, "detached"); // 1.4
  234.  
  235.             var browser = context ? context.browser : this.getCurrentBrowser();
  236.             Firebug.showContext(browser, context);
  237.  
  238.         }
  239.  
  240.     },
  241.  
  242.     undetach: function()
  243.     {
  244.         var detachedChrome = Firebug.chrome;
  245.         Firebug.setChrome(Firebug.originalChrome, "minimized");
  246.  
  247.         Firebug.showBar(false);
  248.         Firebug.resetTooltip();
  249.  
  250.         // when we are done here the window.closed will be true so we don't want to hang on to the ref.
  251.         detachedChrome.window = "This is detached chrome!";
  252.     },
  253.  
  254.     disableOff: function(collapse)
  255.     {
  256.         FBL.collapse($("fbCloseButton"), collapse);  // disable/enable this button in the Firebug.chrome window.
  257.     },
  258.  
  259.     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  260.  
  261.     getBrowsers: function()
  262.     {
  263.           return Firebug.tabBrowser.browsers;
  264.     },
  265.  
  266.     getCurrentBrowser: function()
  267.     {
  268.         return Firebug.tabBrowser.selectedBrowser;
  269.     },
  270.  
  271.     getCurrentURI: function()
  272.     {
  273.         try
  274.         {
  275.             return Firebug.tabBrowser.currentURI;
  276.         }
  277.         catch (exc)
  278.         {
  279.             return null;
  280.         }
  281.     },
  282.  
  283.     getPanelDocument: function(panelType)
  284.     {
  285.         if (!panelType.prototype.parentPanel)
  286.             return panelBar1.browser.contentDocument;
  287.         else
  288.             return panelBar2.browser.contentDocument;
  289.     },
  290.  
  291.     getPanelBrowser: function(panel)
  292.     {
  293.         if (!panel.parentPanel)
  294.             return panelBar1.browser;
  295.         else
  296.             return panelBar2.browser;
  297.     },
  298.  
  299.     savePanels: function()
  300.     {
  301.         var path = this.writePanels(panelBar1.browser.contentDocument);
  302.         $("fbStatusText").setAttribute("value", path);
  303.     },
  304.  
  305.     writePanels: function(doc)
  306.     {
  307.         var serializer = new XMLSerializer();
  308.         var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
  309.                .createInstance(Components.interfaces.nsIFileOutputStream);
  310.         var file = Components.classes["@mozilla.org/file/directory_service;1"]
  311.            .getService(Components.interfaces.nsIProperties)
  312.            .get("TmpD", Components.interfaces.nsIFile);
  313.         file.append("firebug");   // extensions sub-directory
  314.         file.append("panelSave.html");
  315.         file.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666);
  316.         foStream.init(file, 0x02 | 0x08 | 0x20, 0664, 0);   // write, create, truncate
  317.         serializer.serializeToStream(doc, foStream, "");   // rememeber, doc is the DOM tree
  318.         foStream.close();
  319.         return file.path;
  320.     },
  321.  
  322.     updatePanelBar1: function(panelTypes)  // part of initializeUI
  323.     {
  324.         var mainPanelTypes = [];
  325.         for (var i = 0; i < panelTypes.length; ++i)
  326.         {
  327.             var panelType = panelTypes[i];
  328.             if (!panelType.prototype.parentPanel && !panelType.hidden)
  329.                 mainPanelTypes.push(panelType);
  330.         }
  331.         panelBar1.updatePanels(mainPanelTypes);
  332.     },
  333.  
  334.     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  335.  
  336.     getName: function()
  337.     {
  338.         return window ? window.location.href : null;
  339.     },
  340.  
  341.     close: function()
  342.     {
  343.         window.close();
  344.     },
  345.  
  346.     focus: function()
  347.     {
  348.         window.focus();
  349.     },
  350.  
  351.     isFocused: function()
  352.     {
  353.         var winMediator = CCSV("@mozilla.org/appshell/window-mediator;1", "nsIWindowMediator");
  354.  
  355.         return winMediator.getMostRecentWindow(null) == window;
  356.     },
  357.  
  358.     isOpen: function()
  359.     {
  360.         return !($("fbContentBox").collapsed);
  361.     },
  362.  
  363.     reload: function(skipCache)
  364.     {
  365.         var reloadFlags = skipCache
  366.             ? LOAD_FLAGS_BYPASS_PROXY | LOAD_FLAGS_BYPASS_CACHE
  367.             : LOAD_FLAGS_NONE;
  368.  
  369.         // Make sure the selected tab in the attached browser window is refreshed.
  370.         var browser = Firebug.chrome.getCurrentBrowser();
  371.         browser.firebugReload = true;
  372.         browser.webNavigation.reload(reloadFlags);
  373.  
  374.     },
  375.  
  376.     gotoPreviousTab: function()
  377.     {
  378.         if (FirebugContext.previousPanelName)
  379.             this.selectPanel(FirebugContext.previousPanelName);
  380.     },
  381.  
  382.     gotoSiblingTab : function(goRight)
  383.     {
  384.         if ($('fbContentBox').collapsed)
  385.             return;
  386.         var i, currentIndex = newIndex = -1, currentPanel = this.getSelectedPanel(), newPanel;
  387.         var panelTypes = Firebug.getMainPanelTypes(FirebugContext);
  388.         /*get current panel's index (is there a simpler way for this?*/
  389.         for (i = 0; i < panelTypes.length; i++)
  390.         {
  391.             if (panelTypes[i].prototype.name === currentPanel.name)
  392.             {
  393.                 currentIndex = i;
  394.                 break;
  395.             }
  396.         }
  397.         if (currentIndex != -1)
  398.         {
  399.             newIndex = goRight ? (currentIndex == panelTypes.length - 1 ? 0 : ++currentIndex) : (currentIndex == 0 ? panelTypes.length - 1 : --currentIndex);
  400.             newPanel = panelTypes[newIndex].prototype;
  401.             if (newPanel && newPanel.name)
  402.             {
  403.                 this.selectPanel(newPanel.name);
  404.             }
  405.         }
  406.     },
  407.  
  408.     getNextObject: function(reverse)
  409.     {
  410.         var panel = FirebugContext.getPanel(FirebugContext.panelName);
  411.         if (panel)
  412.         {
  413.             var item = panelStatus.getItemByObject(panel.selection);
  414.             if (item)
  415.             {
  416.                 if (reverse)
  417.                     item = item.previousSibling ? item.previousSibling.previousSibling : null;
  418.                 else
  419.                     item = item.nextSibling ? item.nextSibling.nextSibling : null;
  420.  
  421.                 if (item)
  422.                     return item.repObject;
  423.             }
  424.         }
  425.     },
  426.  
  427.     gotoNextObject: function(reverse)
  428.     {
  429.         var nextObject = this.getNextObject(reverse);
  430.         if (nextObject)
  431.             this.select(nextObject);
  432.         else
  433.             beep();
  434.     },
  435.  
  436.     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  437.     // Panels
  438.  
  439.     navigate: function(object, panelName, sidePanelName)
  440.     {
  441.         var panel;
  442.         if (panelName || sidePanelName)
  443.             panel = this.selectPanel(panelName, sidePanelName);
  444.         else
  445.             panel = this.getSelectedPanel();
  446.  
  447.         if (panel)
  448.             panel.navigate(object);
  449.     },
  450.  
  451.     select: function(object, panelName, sidePanelName, forceUpdate)
  452.     {
  453.         var bestPanelName = getBestPanelName(object, FirebugContext, panelName);
  454.         var panel = this.selectPanel(bestPanelName, sidePanelName, true);
  455.         if (panel)
  456.             panel.select(object, forceUpdate);
  457.     },
  458.  
  459.     selectPanel: function(panelName, sidePanelName, noRefresh)
  460.     {
  461.         if (panelName && sidePanelName)
  462.             FirebugContext.sidePanelNames[panelName] = sidePanelName;
  463.  
  464.         return panelBar1.selectPanel(panelName, false, noRefresh);  // cause panel visibility changes and events
  465.     },
  466.  
  467.     selectSidePanel: function(panelName)
  468.     {
  469.         return panelBar2.selectPanel(panelName);
  470.     },
  471.  
  472.     clearPanels: function()
  473.     {
  474.         panelBar1.hideSelectedPanel();
  475.         panelBar1.selectedPanel = null;
  476.         panelBar2.selectedPanel = null;
  477.     },
  478.  
  479.     getSelectedPanel: function()
  480.     {
  481.         return panelBar1.selectedPanel;
  482.     },
  483.  
  484.     getSelectedSidePanel: function()
  485.     {
  486.         return panelBar2.selectedPanel;
  487.     },
  488.  
  489.     switchToPanel: function(context, switchToPanelName)
  490.     {
  491.         // Remember the previous panel and bar state so we can revert if the user cancels
  492.         this.previousPanelName = context.panelName;
  493.         this.previousSidePanelName = context.sidePanelName;
  494.         this.previouslyCollapsed = $("fbContentBox").collapsed;
  495.         this.previouslyFocused = Firebug.isDetached() && this.isFocused();  // TODO previouslyMinimized
  496.  
  497.         var switchPanel = this.selectPanel(switchToPanelName);
  498.         if (switchPanel)
  499.             this.previousObject = switchPanel.selection;
  500.  
  501.         return switchPanel;
  502.     },
  503.  
  504.     unswitchToPanel: function(context, switchToPanelName, cancelled)
  505.     {
  506.         var switchToPanel = context.getPanel(switchToPanelName);
  507.  
  508.         if (this.previouslyFocused)
  509.             this.focus();
  510.  
  511.         if (cancelled && this.previousPanelName)  // revert
  512.         {
  513.             if (this.previouslyCollapsed)
  514.                 Firebug.showBar(false);
  515.  
  516.             if (this.previousPanelName == switchToPanelName)
  517.                 this.select(this.previousObject);
  518.             else
  519.                 this.selectPanel(this.previousPanelName, this.previousSidePanelName);
  520.         }
  521.         else // else stay on the switchToPanel
  522.         {
  523.             this.selectPanel(switchToPanelName);
  524.             if (switchToPanel.selection)
  525.                 this.select(switchToPanel.selection);
  526.             this.getSelectedPanel().panelNode.focus();
  527.         }
  528.  
  529.         delete this.previousObject;
  530.         delete this.previousPanelName;
  531.         delete this.previousSidePanelName;
  532.         delete this.inspectingChrome;
  533.  
  534.         return switchToPanel;
  535.     },
  536.  
  537.     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  538.     // Location interface provider for binding.xml panelFileList
  539.  
  540.     getLocationProvider: function()
  541.     {
  542.         // a function that returns an object with .getObjectDescription() and .getLocationList()
  543.         return function getSelectedPanelFromCurrentContext()
  544.         {
  545.             return Firebug.chrome.getSelectedPanel();  // panels provide location, use the selected panel
  546.         }
  547.     },
  548.  
  549.     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  550.     // UI Synchronization
  551.  
  552.     setFirebugContext: function(context)
  553.     {
  554.          // This sets the global value of FirebugContext in the window that this chrome is compiled into.
  555.          // Note that for firebug.xul, the Firebug object is shared across windows, but not FirebugChrome and FirebugContext
  556.          FirebugContext = context;
  557.  
  558.     },
  559.  
  560.     hidePanel: function()
  561.     {
  562.         if (panelBar1.selectedPanel)
  563.             panelBar1.hideSelectedPanel()
  564.  
  565.         if (panelBar2.selectedPanel)
  566.             panelBar2.hideSelectedPanel()
  567.     },
  568.  
  569.     syncPanel: function()
  570.     {
  571.         panelStatus.clear();
  572.  
  573.         if (FirebugContext)
  574.         {
  575.             var panelName = FirebugContext.panelName
  576.                 ? FirebugContext.panelName
  577.                 : Firebug.defaultPanelName;
  578.  
  579.             // Make HTML panel the default panel, which is displayed
  580.             // to the user the very first time.
  581.             if (!panelName || !Firebug.getPanelType(panelName))
  582.                 panelName = "html";
  583.  
  584.             this.syncMainPanels();
  585.             panelBar1.selectPanel(panelName, true);
  586.         }
  587.         else
  588.         {
  589.             panelBar1.selectPanel(null, true);
  590.         }
  591.  
  592.         if (Firebug.isDetached())
  593.             this.syncTitle();
  594.     },
  595.  
  596.     syncMainPanels: function()
  597.     {
  598.         var panelTypes = Firebug.getMainPanelTypes(FirebugContext);
  599.         panelBar1.updatePanels(panelTypes);
  600.     },
  601.  
  602.     syncSidePanels: function()
  603.     {
  604.         var panelTypes = Firebug.getSidePanelTypes(FirebugContext, panelBar1.selectedPanel);
  605.         panelBar2.updatePanels(panelTypes);
  606.  
  607.         if (FirebugContext && FirebugContext.sidePanelNames)
  608.         {
  609.             var sidePanelName = FirebugContext.sidePanelNames[FirebugContext.panelName];
  610.             sidePanelName = getBestSidePanelName(sidePanelName, panelTypes);
  611.             panelBar2.selectPanel(sidePanelName, true);
  612.         }
  613.         else
  614.             panelBar2.selectPanel(null);
  615.  
  616.         sidePanelDeck.selectedPanel = panelBar2;
  617.         FBL.collapse(sidePanelDeck, !panelBar2.selectedPanel);
  618.         FBL.collapse(panelSplitter, !panelBar2.selectedPanel);
  619.     },
  620.  
  621.     syncTitle: function()
  622.     {
  623.         if (FirebugContext)
  624.         {
  625.             var title = FirebugContext.getTitle();
  626.             window.document.title = FBL.$STRF("WindowTitle", [title]);
  627.         }
  628.         else
  629.             window.document.title = FBL.$STR("Firebug");
  630.     },
  631.  
  632.     focusLocationList: function()
  633.     {
  634.         locationList.popup.showPopup(locationList, -1, -1, "popup", "bottomleft", "topleft");
  635.     },
  636.  
  637.     syncLocationList: function()
  638.     {
  639.         var panel = panelBar1.selectedPanel;
  640.         if (panel && panel.location)
  641.         {
  642.             locationList.location = panel.location;
  643.             FBL.collapse(locationSeparator, false);
  644.             FBL.collapse(locationList, false);
  645.         }
  646.         else
  647.         {
  648.             FBL.collapse(locationSeparator, true);
  649.             FBL.collapse(locationList, true);
  650.         }
  651.     },
  652.  
  653.     clearStatusPath: function()
  654.     {
  655.         panelStatus.clear();
  656.     },
  657.  
  658.     syncStatusPath: function()
  659.     {
  660.         var panel = panelBar1.selectedPanel;
  661.         if (!panel || (panel && !panel.selection))
  662.         {
  663.             panelStatus.clear();
  664.         }
  665.         else
  666.         {
  667.             var path = panel.getObjectPath(panel.selection);
  668.             if (!path || !path.length)
  669.             {
  670.                 FBL.hide(panelStatusSeparator, true);
  671.                 panelStatus.clear();
  672.             }
  673.             else
  674.             {
  675.                 FBL.hide(panelStatusSeparator, false);
  676.  
  677.                 if (panel.name != panelStatus.lastPanelName)
  678.                     panelStatus.clear();
  679.  
  680.                 panelStatus.lastPanelName = panel.name;
  681.  
  682.                 // If the object already exists in the list, just select it and keep the path
  683.                 var selection = panel.selection;
  684.                 var existingItem = panelStatus.getItemByObject(panel.selection);
  685.                 if (existingItem)
  686.                     panelStatus.selectItem(existingItem);
  687.                 else
  688.                 {
  689.                     panelStatus.clear();
  690.  
  691.                     for (var i = 0; i < path.length; ++i)
  692.                     {
  693.                         var object = path[i];
  694.  
  695.                         var rep = Firebug.getRep(object);
  696.                         var objectTitle = rep.getTitle(object, FirebugContext);
  697.  
  698.                         var title = FBL.cropMultipleLines(objectTitle, statusCropSize);
  699.                         panelStatus.addItem(title, object, rep, panel.statusSeparator);
  700.                     }
  701.  
  702.                     panelStatus.selectObject(panel.selection);
  703.                 }
  704.             }
  705.         }
  706.     },
  707.  
  708.     toggleOrient: function()
  709.     {
  710.         var panelPane = $("fbPanelPane");
  711.         panelSplitter.orient = panelPane.orient
  712.             = panelPane.orient == "vertical" ? "horizontal" : "vertical";
  713.         var option = $('menu_toggleOrient').getAttribute("option");
  714.         Firebug.setPref(Firebug.prefDomain, option, panelPane.orient != "vertical");
  715.     },
  716.  
  717.     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  718.  
  719.     addTab: function(context, url, title, parentPanel)
  720.     {
  721.         context.addPanelType(url, title, parentPanel);
  722.         if (context == FirebugContext)
  723.         {
  724.             if (parentPanel)
  725.             {
  726.                 var currentPanel = this.getSelectedPanel();
  727.                 if (currentPanel && parentPanel == currentPanel.name)
  728.                     this.syncSidePanels();
  729.             }
  730.             else
  731.             {
  732.                 this.syncMainPanels();
  733.             }
  734.         }
  735.     },
  736.  
  737.     removeTab: function(context, url)
  738.     {
  739.         context.removePanelType(url);
  740.     },
  741.  
  742.     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  743.  
  744.     getGlobalAttribute: function(id, name)
  745.     {
  746.         var elt = $(id);
  747.         return elt.getAttribute(name);
  748.     },
  749.  
  750.     setGlobalAttribute: function(id, name, value)
  751.     {
  752.         var elt = $(id);
  753.         if (elt)
  754.         {
  755.             if (value == null)
  756.                 elt.removeAttribute(name);
  757.             else
  758.                 elt.setAttribute(name, value);
  759.         }
  760.  
  761.         if (Firebug.externalChrome)
  762.             Firebug.externalChrome.setGlobalAttribute(id, name, value);
  763.     },
  764.  
  765.  
  766.     setChromeDocumentAttribute: function(id, name, value)
  767.     {
  768.         // Call as  Firebug.chrome.setChromeDocumentAttribute() to set attributes in another window.
  769.         var elt = $(id);
  770.         if (elt)
  771.             elt.setAttribute(name, value);
  772.     },
  773.  
  774.     keyCodeListen: function(key, filter, listener, capture)
  775.     {
  776.         if (!filter)
  777.             filter = FBL.noKeyModifiers;
  778.  
  779.         var keyCode = KeyEvent["DOM_VK_"+key];
  780.  
  781.         function fn(event)
  782.         {
  783.             if (event.keyCode == keyCode && (!filter || filter(event)))
  784.             {
  785.                 listener();
  786.                 FBL.cancelEvent(event);
  787.             }
  788.         }
  789.  
  790.         window.addEventListener("keypress", fn, capture);
  791.  
  792.         return [fn, capture];
  793.     },
  794.  
  795.     keyListen: function(ch, filter, listener, capture)
  796.     {
  797.         if (!filter)
  798.             filter = FBL.noKeyModifiers;
  799.  
  800.         var charCode = ch.charCodeAt(0);
  801.  
  802.         function fn(event)
  803.         {
  804.             if (event.charCode == charCode && (!filter || filter(event)))
  805.             {
  806.                 listener();
  807.                 FBL.cancelEvent(event);
  808.             }
  809.         }
  810.  
  811.         window.addEventListener("keypress", fn, capture);
  812.  
  813.         return [fn, capture];
  814.     },
  815.  
  816.     keyIgnore: function(listener)
  817.     {
  818.         window.removeEventListener("keypress", listener[0], listener[1]);
  819.     },
  820.  
  821.     $: function(id)
  822.     {
  823.         return $(id);
  824.     },
  825.  
  826.     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  827.  
  828.     applyTextSize: function(value)
  829.     {
  830.         var zoom = value >= 0 ? positiveZoomFactors[value] : negativeZoomFactors[Math.abs(value)];
  831.  
  832.         panelBar1.browser.markupDocumentViewer.textZoom = zoom;
  833.         panelBar2.browser.markupDocumentViewer.textZoom = zoom;
  834.     },
  835.  
  836.     obeyOmitObjectPathStack: function(value)
  837.     {
  838.         FBL.hide(panelStatus, (value?true:false));
  839.     },
  840.  
  841.     getPanelStatusElements: function()
  842.     {
  843.         return panelStatus;
  844.     },
  845.  
  846.     // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  847.     // UI Event Listeners uilisteners  or "panelListeners"
  848.  
  849.     onPanelNavigate: function(object, panel)
  850.     {
  851.         this.syncLocationList();
  852.     },
  853.  
  854.     onObjectSelected: function(object, panel)
  855.     {
  856.         if (panel == panelBar1.selectedPanel)
  857.         {
  858.             this.syncStatusPath();
  859.  
  860.             var sidePanel = panelBar2.selectedPanel;
  861.             if (sidePanel)
  862.                 sidePanel.select(object);
  863.         }
  864.     },
  865.  
  866.     onApplyDecorator: function(sourceBox) // called on setTimeout after sourceBox viewport has been repainted
  867.     {
  868.     },
  869.  
  870.     onViewportChange: function(sourceLink) // called on scrollTo, passing in the selected line
  871.     {
  872.     },
  873.  
  874.     showUI: function(browser, context) // called when the Firebug UI comes up in browser or detached
  875.     {
  876.     },
  877.  
  878.     hideUI: function(browser, context)  // called when the Firebug UI comes down; context may be null
  879.     {
  880.     },
  881.  
  882.     //* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  883.  
  884.     onOptionsShowing: function(popup)
  885.     {
  886.         for (var child = popup.firstChild; child; child = child.nextSibling)
  887.         {
  888.             if (child.localName == "menuitem")
  889.             {
  890.                 var option = child.getAttribute("option");
  891.                 if (option)
  892.                 {
  893.                     var checked = false;
  894.                     if (option == "profiling")
  895.                         checked = fbs.profiling;
  896.                     else
  897.                         checked = Firebug.getPref(Firebug.prefDomain, option);
  898.  
  899.                     child.setAttribute("checked", checked);
  900.                 }
  901.             }
  902.         }
  903.     },
  904.  
  905.     onToggleOption: function(menuitem)
  906.     {
  907.         var option = menuitem.getAttribute("option");
  908.         var checked = menuitem.getAttribute("checked") == "true";
  909.  
  910.         Firebug.setPref(Firebug.prefDomain, option, checked);
  911.     },
  912.  
  913.     onContextShowing: function(event)
  914.     {
  915.         // xxxHonza: This context-menu support can be used even in separate window, which
  916.         // doesn't contain the FBUI (panels).
  917.         //if (!panelBar1.selectedPanel)
  918.         //    return false;
  919.  
  920.         var popup = $("fbContextMenu");
  921.         var target = document.popupNode;
  922.         var panel = target ? Firebug.getElementPanel(target) : null;
  923.  
  924.         if (!panel)
  925.             panel = panelBar1 ? panelBar1.selectedPanel : null; // the event must be on our chrome not inside the panel
  926.  
  927.         FBL.eraseNode(popup);
  928.  
  929.         // Make sure the Copy action is only available if there is actually someting
  930.         // selected in the panel.
  931.         var sel = target.ownerDocument.defaultView.getSelection();
  932.         if (!this.contextMenuObject && !$("cmd_copy").getAttribute("disabled") && !sel.isCollapsed)
  933.         {
  934.             var menuitem = FBL.createMenuItem(popup, {label: "Copy"});
  935.             menuitem.setAttribute("command", "cmd_copy");
  936.         }
  937.  
  938.         var object;
  939.         if (this.contextMenuObject)
  940.             object = this.contextMenuObject;
  941.         else if (target && target.ownerDocument == document)
  942.             object = Firebug.getRepObject(target);
  943.         else if (target && panel)
  944.             object = panel.getPopupObject(target);
  945.         else if (target)
  946.             object = Firebug.getRepObject(target); // xxxHonza: What about a node from different document? Is that OK?
  947.  
  948.         this.contextMenuObject = null;
  949.  
  950.         var rep = Firebug.getRep(object);
  951.         var realObject = rep ? rep.getRealObject(object, FirebugContext) : null;
  952.         var realRep = realObject ? Firebug.getRep(realObject) : null;
  953.  
  954.         if (realObject && realRep)
  955.         {
  956.             // 1. Add the custom menu items from the realRep
  957.             var menu = realRep.getContextMenuItems(realObject, target, FirebugContext);
  958.             if (menu)
  959.             {
  960.                 for (var i = 0; i < menu.length; ++i)
  961.                     FBL.createMenuItem(popup, menu[i]);
  962.             }
  963.         }
  964.  
  965.         if (object && rep && rep != realRep)
  966.         {
  967.             // 1. Add the custom menu items from the original rep
  968.             var items = rep.getContextMenuItems(object, target, FirebugContext);
  969.             if (items)
  970.             {
  971.                 for (var i = 0; i < items.length; ++i)
  972.                     FBL.createMenuItem(popup, items[i]);
  973.             }
  974.         }
  975.  
  976.         // 1. Add the custom menu items from the panel
  977.         if (panel)
  978.         {
  979.             var items = panel.getContextMenuItems(realObject, target);
  980.             if (items)
  981.             {
  982.                 for (var i = 0; i < items.length; ++i)
  983.                     FBL.createMenuItem(popup, items[i]);
  984.             }
  985.         }
  986.  
  987.         // 2. Add the inspect menu items
  988.         if (realObject && rep && rep.inspectable)
  989.         {
  990.             var separator = null;
  991.  
  992.             var items = this.getInspectMenuItems(realObject);
  993.             for (var i = 0; i < items.length; ++i)
  994.             {
  995.                 if (popup.firstChild && !separator)
  996.                     separator = FBL.createMenuSeparator(popup);
  997.  
  998.                 FBL.createMenuItem(popup, items[i]);
  999.             }
  1000.         }
  1001.  
  1002.         if (!popup.firstChild)
  1003.             return false;
  1004.     },
  1005.  
  1006.     onEditorsShowing: function(popup)  // TODO move to Firebug.Editors module in editors.js
  1007.     {
  1008.         var editors = Firebug.registeredEditors;
  1009.         if ( editors.length > 0 )
  1010.         {
  1011.             var lastChild = popup.lastChild;
  1012.             FBL.eraseNode(popup);
  1013.             var disabled = (!FirebugContext);
  1014.             for( var i = 0; i < editors.length; ++i )
  1015.             {
  1016.                 if (editors[i] == "-")
  1017.                 {
  1018.                     FBL.createMenuItem(popup, "-");
  1019.                     continue;
  1020.                 }
  1021.                 var item = {label: editors[i].label, image: editors[i].image,
  1022.                                 nol10n: true, disabled: disabled };
  1023.                 var menuitem = FBL.createMenuItem(popup, item);
  1024.                 menuitem.setAttribute("command", "cmd_openInEditor");
  1025.                 menuitem.value = editors[i].id;
  1026.             }
  1027.             FBL.createMenuItem(popup, "-");
  1028.             popup.appendChild(lastChild);
  1029.         }
  1030.     },
  1031.  
  1032.     getInspectMenuItems: function(object)
  1033.     {
  1034.         var items = [];
  1035.  
  1036.         // Domplate (+ support for context menus) can be used even in separate
  1037.         // windows when FirebugContext doesn't have to be defined.
  1038.         if (!FirebugContext)
  1039.             return items;
  1040.  
  1041.         for (var i = 0; i < Firebug.panelTypes.length; ++i)
  1042.         {
  1043.             var panelType = Firebug.panelTypes[i];
  1044.             if (!panelType.prototype.parentPanel
  1045.                 && panelType.prototype.name != FirebugContext.panelName
  1046.                 && panelSupportsObject(panelType, object))
  1047.             {
  1048.                 var panelName = panelType.prototype.name;
  1049.  
  1050.                 var title = Firebug.getPanelTitle(panelType);
  1051.                 var label = FBL.$STRF("InspectInTab", [title]);
  1052.  
  1053.                 var command = bindFixed(this.select, this, object, panelName);
  1054.                 items.push({label: label, command: command, nol10n: true});
  1055.             }
  1056.         }
  1057.  
  1058.         return items;
  1059.     },
  1060.  
  1061.     onTooltipShowing: function(event)
  1062.     {
  1063.         // xxxHonza: This tooltip support can be used even in separate window, which
  1064.         // doesn't contain the FBUI (panels).
  1065.         //if (!panelBar1.selectedPanel)
  1066.         //    return false;
  1067.  
  1068.         var tooltip = $("fbTooltip");
  1069.         var target = document.tooltipNode;
  1070.  
  1071.         var panel = target ? Firebug.getElementPanel(target) : null;
  1072.  
  1073.         var object;
  1074.         /* XXXjjb This causes the Script panel to show the function body over and over. We need to clear it at least,
  1075.          * but really we need to understand why the tooltip should show the context menu object at all.
  1076.          * One thing the contextMenuObject supports is peeking at function bodies when stopped a breakpoint.
  1077.          * That case could be supported with clearing the contextMenuObject, but we don't know if that breaks
  1078.          * something else. So maybe a popupMenuObject should be set on the context if that is what we want to support
  1079.          * The other complication is that there seems to be another tooltip.
  1080.         if (this.contextMenuObject)
  1081.         {
  1082.             object = this.contextMenuObject;
  1083.             FBTrace.sysout("tooltip by contextMenuObject");
  1084.         }
  1085.         else*/
  1086.         if (target && target.ownerDocument == document)
  1087.             object = Firebug.getRepObject(target);
  1088.         else if (panel)
  1089.             object = panel.getTooltipObject(target);
  1090.  
  1091.         var rep = object ? Firebug.getRep(object) : null;
  1092.         object = rep ? rep.getRealObject(object, FirebugContext) : null;
  1093.         rep = object ? Firebug.getRep(object) : null;
  1094.  
  1095.         if (object && rep)
  1096.         {
  1097.             var label = rep.getTooltip(object, FirebugContext);
  1098.             if (label)
  1099.             {
  1100.                 tooltip.setAttribute("label", label);
  1101.                 return true;
  1102.             }
  1103.         }
  1104.  
  1105.         if (FBL.hasClass(target, 'noteInToolTip'))
  1106.             FBL.setClass(tooltip, 'noteInToolTip');
  1107.         else
  1108.             FBL.removeClass(tooltip, 'noteInToolTip');
  1109.  
  1110.         if (target.hasAttribute("title"))
  1111.         {
  1112.             tooltip.setAttribute("label", target.getAttribute("title"));
  1113.             return true;
  1114.         }
  1115.  
  1116.         return false;
  1117.     },
  1118.  
  1119.     openAboutDialog: function()
  1120.     {
  1121.         var extensionManager = CCSV("@mozilla.org/extensions/manager;1", "nsIExtensionManager");
  1122.         openDialog("chrome://mozapps/content/extensions/about.xul", "",
  1123.             "chrome,centerscreen,modal", "urn:mozilla:item:firebug@software.joehewitt.com", extensionManager.datasource);
  1124.     },
  1125.  
  1126.     breakOnNext: function(context, event)
  1127.     {
  1128.         // Avoid bubbling from associated options.
  1129.         if (event.target.id != "cmd_breakOnNext")
  1130.             return;
  1131.  
  1132.         if (!context)
  1133.         {
  1134.             return;
  1135.         }
  1136.  
  1137.         var panel = panelBar1.selectedPanel;
  1138.  
  1139.         if (panel && panel.breakable)
  1140.             Firebug.Breakpoint.toggleBreakOnNext(panel);
  1141.     },
  1142. };
  1143.  
  1144. // ************************************************************************************************
  1145. // Local Helpers
  1146.  
  1147. function panelSupportsObject(panelType, object)
  1148. {
  1149.     if (panelType)
  1150.     {
  1151.         try {
  1152.             // This tends to throw exceptions often because some objects are weird
  1153.             return panelType.prototype.supportsObject(object)
  1154.         } catch (exc) {}
  1155.     }
  1156.  
  1157.     return 0;
  1158. }
  1159.  
  1160. function getBestPanelName(object, context, panelName)
  1161. {
  1162.     if (!panelName)
  1163.         panelName = context.panelName;
  1164.  
  1165.     // Check if the suggested panel name supports the object, and if so, go with it
  1166.     if (panelName)
  1167.     {
  1168.         panelType = Firebug.getPanelType(panelName);
  1169.         if (panelSupportsObject(panelType, object))
  1170.             return panelType.prototype.name;
  1171.     }
  1172.  
  1173.     // The suggested name didn't pan out, so search for the panel type with the
  1174.     // most specific level of support
  1175.  
  1176.     var bestLevel = 0;
  1177.     var bestPanel = null;
  1178.  
  1179.     for (var i = 0; i < Firebug.panelTypes.length; ++i)
  1180.     {
  1181.         var panelType = Firebug.panelTypes[i];
  1182.         if (!panelType.prototype.parentPanel)
  1183.         {
  1184.             var level = panelSupportsObject(panelType, object);
  1185.             if (!bestLevel || (level && (level > bestLevel) ))
  1186.             {
  1187.                 bestLevel = level;
  1188.                 bestPanel = panelType;
  1189.             }
  1190.         }
  1191.     }
  1192.  
  1193.     return bestPanel ? bestPanel.prototype.name : null;
  1194. }
  1195.  
  1196. function getBestSidePanelName(sidePanelName, panelTypes)
  1197. {
  1198.     if (sidePanelName)
  1199.     {
  1200.         // Verify that the suggested panel name is in the acceptable list
  1201.         for (var i = 0; i < panelTypes.length; ++i)
  1202.         {
  1203.             if (panelTypes[i].prototype.name == sidePanelName)
  1204.                 return sidePanelName;
  1205.         }
  1206.     }
  1207.  
  1208.     // Default to the first panel type in the list
  1209.     return panelTypes.length ? panelTypes[0].prototype.name : null;
  1210. }
  1211.  
  1212. // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  1213. // Event listeners
  1214.  
  1215. function browser1Loaded()
  1216. {
  1217.     var browser1 = panelBar1.browser;
  1218.     browser1.removeEventListener("load", browser1Loaded, true);
  1219.  
  1220.     browser1.contentDocument.title = "Firebug Main Panel";
  1221.     browser1Loaded.complete = true;
  1222.  
  1223.     if (browser1Loaded.complete && browser2Loaded.complete)
  1224.         FirebugChrome.initializeUI();
  1225. }
  1226.  
  1227. function browser2Loaded()
  1228. {
  1229.     var browser2 = panelBar2.browser;
  1230.     browser2.removeEventListener("load", browser2Loaded, true);
  1231.  
  1232.     browser2.contentDocument.title = "Firebug Side Panel";
  1233.     browser2Loaded.complete = true;
  1234.  
  1235.     if (browser1Loaded.complete && browser2Loaded.complete)
  1236.         FirebugChrome.initializeUI();  // the chrome bound into this scope
  1237.  
  1238. }
  1239.  
  1240. function onBlur(event)
  1241. {
  1242.     // XXXjjb this seems like a waste: called continuously to clear possible highlight I guess.
  1243.     // XXXhh Is this really necessary? I disabled it for now as this was preventing me to show highlights on focus
  1244.     //Firebug.Inspector.highlightObject(null, FirebugContext);
  1245. }
  1246.  
  1247. function onSelectLocation(event)
  1248. {
  1249.     var location = locationList.repObject;
  1250.     FirebugChrome.navigate(location);
  1251. }
  1252.  
  1253. function onSelectingPanel(event)
  1254. {
  1255.     var panel = panelBar1.selectedPanel;
  1256.     var panelName = panel ? panel.name : null;
  1257.     if (FirebugContext)
  1258.     {
  1259.         FirebugContext.previousPanelName = FirebugContext.panelName;
  1260.         FirebugContext.panelName = panelName;
  1261.  
  1262.         FirebugContext.sidePanelName =
  1263.             FirebugContext.sidePanelNames && panelName in FirebugContext.sidePanelNames
  1264.             ? FirebugContext.sidePanelNames[panelName]
  1265.             : null;
  1266.     }
  1267.  
  1268.     if (panel)
  1269.     {
  1270.         panel.navigate(panel.location);
  1271.         Firebug.chrome.syncLocationList();
  1272.         Firebug.chrome.syncSidePanels();
  1273.         Firebug.chrome.syncStatusPath();
  1274.  
  1275.         Firebug.showPanel(panel.context.browser, panel);
  1276.     }
  1277.     else
  1278.     {
  1279.         var browser = FirebugChrome.getCurrentBrowser();
  1280.         Firebug.showPanel(browser, null);
  1281.     }
  1282. }
  1283.  
  1284. function onSelectedSidePanel(event)
  1285. {
  1286.     var sidePanel = panelBar2.selectedPanel;
  1287.     if (FirebugContext)
  1288.     {
  1289.         var panelName = FirebugContext.panelName;
  1290.         if (panelName)
  1291.         {
  1292.             var sidePanelName = sidePanel ? sidePanel.name : null;
  1293.             FirebugContext.sidePanelNames[panelName] = sidePanelName;
  1294.         }
  1295.         else
  1296.         {
  1297.         }
  1298.     }
  1299.     var panel = panelBar1.selectedPanel;
  1300.     if (panel && sidePanel)
  1301.         sidePanel.select(panel.selection);
  1302.  
  1303.     var browser = sidePanel ? sidePanel.context.browser : FirebugChrome.getCurrentBrowser();
  1304.     Firebug.showSidePanel(browser, sidePanel);  // dispatch to modules
  1305. }
  1306.  
  1307. function onPanelMouseOver(event)
  1308. {
  1309.     var object = Firebug.getRepObject(event.target);
  1310.     if (object)
  1311.     {
  1312.         var realObject = getRealObject(object);
  1313.         if (realObject)
  1314.             Firebug.Inspector.highlightObject(realObject, FirebugContext);
  1315.     }
  1316. }
  1317.  
  1318. function onPanelMouseOut(event)
  1319. {
  1320.     Firebug.Inspector.highlightObject(null);
  1321. }
  1322.  
  1323. function onPanelClick(event)
  1324. {
  1325.     var repNode = Firebug.getRepNode(event.target);
  1326.     if (repNode)
  1327.     {
  1328.         var object = repNode.repObject;
  1329.         var rep = Firebug.getRep(object);
  1330.         var realObject = rep ? rep.getRealObject(object, FirebugContext) : null;
  1331.         var realRep = realObject ? Firebug.getRep(realObject) : rep;
  1332.         if (!realObject)
  1333.             realObject = object;
  1334.  
  1335.         if (FBL.isLeftClick(event))
  1336.         {
  1337.             if (FBL.hasClass(repNode, "objectLink"))
  1338.             {
  1339.                 if (realRep)
  1340.                 {
  1341.                     realRep.inspectObject(realObject, FirebugContext);
  1342.                     FBL.cancelEvent(event);
  1343.                 }
  1344.             }
  1345.         }
  1346.         else if (FBL.isControlClick(event) || FBL.isMiddleClick(event))
  1347.         {
  1348.             if (!realRep || !realRep.browseObject(realObject, FirebugContext))
  1349.             {
  1350.                 if (rep && !(rep != realRep && rep.browseObject(object, FirebugContext)))
  1351.                 {
  1352.                     var panel = Firebug.getElementPanel(event.target);
  1353.                     if (!panel || !panel.browseObject(realObject))
  1354.                         return;
  1355.                 }
  1356.             }
  1357.             FBL.cancelEvent(event);
  1358.         }
  1359.     }
  1360. }
  1361.  
  1362. function onPanelMouseDown(event)
  1363. {
  1364.     if (FBL.isLeftClick(event))
  1365.     {
  1366.         var editable = FBL.getAncestorByClass(event.target, "editable");
  1367.         if (editable)
  1368.         {
  1369.             Firebug.Editor.startEditing(editable);
  1370.             FBL.cancelEvent(event);
  1371.         }
  1372.     }
  1373.     else if (FBL.isMiddleClick(event) && Firebug.getRepNode(event.target))
  1374.     {
  1375.         // Prevent auto-scroll when middle-clicking a rep object
  1376.         FBL.cancelEvent(event);
  1377.     }
  1378. }
  1379.  
  1380. function onMainTabBoxMouseDown(event)
  1381. {
  1382.     if (Firebug.isInBrowser())
  1383.     {
  1384.         var contentSplitter = Firebug.chrome.$("fbContentSplitter");
  1385.     }
  1386. }
  1387.  
  1388. function getRealObject(object)
  1389. {
  1390.     var rep = Firebug.getRep(object);
  1391.     var realObject = rep ? rep.getRealObject(object, FirebugContext) : null;
  1392.     return realObject ? realObject : object;
  1393. }
  1394.  
  1395.  
  1396. // ************************************************************************************************
  1397. // Utils (duplicated from lib.js)
  1398.  
  1399. function $(id, doc)
  1400. {
  1401.     if (doc)
  1402.         return doc.getElementById(id);
  1403.     else
  1404.         return document.getElementById(id);
  1405. }
  1406.  
  1407. function cloneArray(array, fn)
  1408. {
  1409.    var newArray = [];
  1410.  
  1411.    for (var i = 0; i < array.length; ++i)
  1412.        newArray.push(array[i]);
  1413.  
  1414.    return newArray;
  1415. }
  1416.  
  1417. function bindFixed()
  1418. {
  1419.     var args = cloneArray(arguments), fn = args.shift(), object = args.shift();
  1420.     return function() { return fn.apply(object, args); }
  1421. }
  1422.  
  1423. }})();
  1424.  
  1425. // ************************************************************************************************
  1426.  
  1427. // XXXjoe This horrible hack works around a focus bug in Firefox which is caused when
  1428. // the HTML Validator extension and Firebug are installed.  It causes the keyboard to
  1429. // behave erratically when typing, and the only solution I've found is to delay
  1430. // the initialization of HTML Validator by overriding this function with a timeout.
  1431. // XXXrobc Do we still need this? Does this extension even exist anymore?
  1432. if (top.hasOwnProperty('TidyBrowser'))
  1433. {
  1434.     var prev = TidyBrowser.prototype.updateStatusBar;
  1435.     TidyBrowser.prototype.updateStatusBar = function()
  1436.     {
  1437.         var self = this, args = arguments;
  1438.         setTimeout(function()
  1439.         {
  1440.             prev.apply(self, args);
  1441.         });
  1442.     }
  1443. }
  1444.  
  1445. // ************************************************************************************************
  1446.  
  1447. function dddx()
  1448. {
  1449.     Firebug.Console.logFormatted(arguments);
  1450. }
  1451.  
  1452.  
  1453.  
  1454.